package com.heima.service.Impl;

import com.alibaba.fastjson.JSONArray;
import com.heima.aliyun.GreenImageScan;
import com.heima.aliyun.GreenTextScan;
import com.heima.common.exception.CustException;
import com.heima.feign.AdminFeign;
import com.heima.mapper.WmNewsMapper;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.message.PublishArticleConstants;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.service.WmNewsAutoScanService;
import com.heima.utils.common.SensitiveWordUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {
  @Value("${file.oss.web-site}")
  String webSite;

  @Autowired
  WmNewsMapper wmNewsMapper;
  @Autowired AdminFeign adminFeign;
  @Autowired
  GreenTextScan greenTextScan;
  @Autowired
    GreenImageScan greenImageScan;
  @Autowired
    RabbitTemplate rabbitTemplate;

  @Override
  @Transactional
  public void autoScanWmNews(Integer id) {
    // 参数判断
    if (id == null) {
      CustException.cust(AppHttpCodeEnum.PARAM_INVALID, "id文本为空");
    }
    // 判断是否存在
    WmNews wmNews = wmNewsMapper.selectById(id);
    if (wmNews == null) {
      CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "用户不存在");
    }
    //        判断文章的状态是否为1
    if (wmNews.getStatus() == WmNews.Status.SUBMIT.getCode()) {
      // 抽取文章的所有文本内容，和图片
      //        Map<String, Object> { content ：文本内容，images list<String> 图片路径集合}
      Map<String, Object> map = handlTextAndImages(wmNews);


        String content = (String) map.get("content");
        List<String> images = (List<String>) map.get("images");
      // 敏感词审核
      if (StringUtils.isNotBlank(content)) {
        boolean hanglsensitive = handlSensitiveaWord(content, wmNews);
        if (!hanglsensitive) return;
        log.info("敏感词审核通过了");

        // 阿里云的文本审核

        boolean isTextSacn = handTextScan(content, wmNews);
        if (!isTextSacn) return;
        log.info("阿里云文本自动审核通过了");
        }
      // 阿里云的图片审核
      if (images != null) {

        boolean isImagesScan = handImageScan(images, wmNews);
        if (!isImagesScan) return;
        log.info("阿里云图片自动审核通过了");
        }
      // 改变文章的状态为8
        updateWmNews(wmNews,WmNews.Status.SUCCESS.getCode(),"审核通过，待发布文章");
      // 文章发布功能发送消息，通知发布文章
        Long publishTime = wmNews.getPublishTime().getTime();
        Long nowTime = new Date().getTime();
        Long realTime = publishTime-nowTime;
        if (realTime<=0){
            //则hi
            rabbitTemplate.convertAndSend(PublishArticleConstants.PUBLISH_ARTICLE_EXCHANGE,
                    PublishArticleConstants.PUBLISH_ARTICLE_ROUTE_KEY,
                    wmNews.getId());
                log.info("自动审核通过 消息发布,文章id:{}",wmNews.getId());
        }
        else {
            //延迟发布消息
            rabbitTemplate.convertAndSend(PublishArticleConstants.PUBLISH_ARTICLE_EXCHANGE,
                                        PublishArticleConstants.PUBLISH_ARTICLE_DEAD_ROUTE_KEY,
                                        wmNews.getId(),
                                        message -> {
                        message.getMessageProperties().setExpiration(String.valueOf(realTime));
                        return message;
                                        }

            );
            log.info("自动审核，延迟队列发送消息成功，延迟的时间：{}，文章的id",realTime,wmNews.getId());
            }
        }

  }
    /**
     * 阿里云的图片审核
     * @param images
     * @param wmNews
     * @return
     */

    private boolean handImageScan(List<String>images, WmNews wmNews) {
      boolean flag =true;
        try {
            log.info("开始图片的自动审核");
            Map map = greenImageScan.imageUrlScan(images);
            //获取对应的审核结果
            String suggestion = (String) map.get("suggestion");
            if ("block".equals(suggestion)){
                log.info("图片审核失败有违规内容");
                //修改文章的状态为2,s审核失败
                updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"t图片自动审核失败，有违规词汇");
                flag=false;
            }
            if ("reviem".equals(suggestion)){
                log.info("图片中存在不确定的因素，转人工审核");
                updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"图片不确定，需要转人工审核");
                flag=false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("图片的自动审核失败，需要转人工审核");
            updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"转人工审核");
        }
        return flag;
    }
    /**
     * 阿里云自动审核文章。
     * @param content
     * @param wmNews
     * @return
     */
    private boolean handTextScan(String  content, WmNews wmNews) {
      boolean flag = true;
        try {
            //进行自动审核
            log.info("开始文本的自动审核");
            Map map = greenTextScan.greenTextScan(content);
            //获取对应的审核结果
            String suggestion = (String) map.get("suggestion");
            if ("block".equals(suggestion)){
                log.info("审核失败有违规内容");
                //修改文章的状态为2,s审核失败
                updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"自动审核失败，有违规词汇");
                flag=false;
            }
            if ("reviem".equals(suggestion)){
                log.info("存在不确定的因素，转人工审核");
                updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"不确定，需要转人工审核");
                flag=false;
            }

        } catch (Exception e) {
            e.printStackTrace();
            log.info("自动审核失败，需要转人工审核");
            updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"转人工审核");
        }


        return flag;
    }

    /**
   * 敏感词的处理
   *
   * @param content
   * @param wmNews
   * @return
   */
  private boolean handlSensitiveaWord(String content, WmNews wmNews) {
    boolean flag = true;
    // 查询数据的敏感词
      log.info("开始敏感词的审核");
    ResponseResult<List<String>> listResponseResult = adminFeign.selectAllChannel();
    if (listResponseResult == null) {
      CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "查询敏感词库失败");
    }
    List<String> data = listResponseResult.getData();
    // 将敏感词集合DFA的数据结构
    SensitiveWordUtil.initMap(data);

    // 敏感词检测
    Map<String, Integer> words = SensitiveWordUtil.matchWords(content);

    if (!CollectionUtils.isEmpty(words) && words.size() > 0) {
        // 将文章的状态修改为2
      updateWmNews(wmNews, WmNews.Status.FAIL.getCode(), "存在敏感词" + words);
      flag = false;
    }

    return flag;
  }

  /**
   * 对文章的conent的文本进行抽取content,和images
   *
   * @param wmNews
   * @return
   */
  private Map<String, Object> handlTextAndImages(WmNews wmNews) {
    // 获取文本
    String content = wmNews.getContent();
    if (StringUtils.isBlank(content)) {
      CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "文章不存在");
    }
    // 抽取其中的文本为map对象
    List<Map> contextMap = JSONArray.parseArray(content, Map.class);
    String text =
        contextMap.stream()
            .filter(map -> "text".equals(map.get("type")))
            .map(map -> (String) map.get("value"))
            .collect(Collectors.joining(","));
    // 将文本内容和标题进行合并
    String contentd = text + "," + wmNews.getTitle();
    // 2. 抽取文章中所有图片   content :  全路径       images :  文件名称  + 访问前缀
    List<String> imageList =
        contextMap.stream()
            .filter(map -> "text".equals(map.get("type")))
            .map(map -> (String) map.get("value"))
            .collect(Collectors.toList());
    // 按照 逗号 切割封面字符串  得到数组   基于数组得到stream   将每一条数据都拼接一个前缀 收集成集合
    if (wmNews.getImages() != null) {
      List<String> urlImages =
          Arrays.stream(wmNews.getImages().split(","))
              .map(url -> webSite + url)
              .collect(Collectors.toList());
      imageList.addAll(urlImages);
    }
    // 3. 去重
    imageList.stream().distinct().collect(Collectors.toList());
    HashMap<String, Object> reust = new HashMap<>();

    reust.put("content", text);
    reust.put("images", imageList);
    return reust;
  }

  /**
   * 修改文章的状态，并返回原因
   *
   * @param wmNews
   * @param status
   * @param reason
   */
  private void updateWmNews(WmNews wmNews, Short status, String reason) {
    wmNews.setStatus(status);
    wmNews.setReason(reason);
    wmNewsMapper.updateById(wmNews);
  }
}
